package service;

import com.squareup.javapoet.*;
import common.constants.ProjectPath;
import common.core.BaseDDL;
import common.core.BaseService;
import dto.TableDto;
import dto.TableListDto;
import jws.dal.annotation.*;
import utils.FileUtils;
import utils.FormatUtils;
import utils.DBUtils;
import javax.lang.model.element.Modifier;
import java.io.IOException;
import java.math.*;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * Created by cxland on 2017/9/21.
 */
public class GenCodeService {

    public  static void generateDao(String tableName, String filePath, String pgName) throws  IOException{

        /**
         * 类构造器
         */
        String packageName = FormatUtils.toLowercase(FormatUtils.lineToHump(tableName));
        if (!pgName.equals("/")){
            packageName = pgName;
        }
        String path=filePath+ProjectPath.MG_WORLD+packageName+"/dao";
        String className = FormatUtils.captureName(FormatUtils.lineToHump(tableName))+"Dao";
        String ddlName = FormatUtils.captureName(FormatUtils.lineToHump(tableName))+"DDL";
        String ddlImport = "import modules."+packageName+".ddl."+ddlName+";";
        String daoImport = "import common.core.BaseDao";

        TypeName A = TypeVariableName.get("BaseDao<"+ddlName+">");
        TypeSpec typeSpec = TypeSpec.classBuilder(className)//类名
                .addModifiers(Modifier.PUBLIC)
                .superclass(A)
                .build();

        JavaFile javaFile = JavaFile.builder("modules."+packageName+".dao;\n"+ddlImport+"\n"+daoImport, typeSpec).skipJavaLangImports(true)
                .build();
      //  javaFile.writeTo(System.out);
        FileUtils.writeJavaFile(path,className+".java",javaFile.toString());
    }

    /**
     * 生成Service
     * @throws IOException
     */
    public static void generateService(String tableName, String filePath, String pgName) throws  IOException{
        /**
         * 类构造器
         */
        String packageName = FormatUtils.toLowercase(FormatUtils.lineToHump(tableName));
        if (! pgName.equals("/")) {
            packageName =  pgName;
        }

        String path=filePath+ProjectPath.MG_WORLD+packageName+"/service";
        String className = FormatUtils.captureName(FormatUtils.lineToHump(tableName))+"Service";

        TypeSpec typeSpec = TypeSpec.classBuilder(className)//类名
                .addModifiers(Modifier.PUBLIC)
                .superclass(BaseService.class)
                .build();

        JavaFile javaFile = JavaFile.builder("modules."+packageName+".service", typeSpec).skipJavaLangImports(true)
                .build();
     //   javaFile.writeTo(System.out);
        FileUtils.writeJavaFile(path,className+".java",javaFile.toString());
    }

    /**
     * 生成DDL
     * @throws IOException
     * @throws SQLException
     * @throws ClassNotFoundException
     */
    public static void generateDDL(String tableName, String filePath, String pgName) throws IOException,SQLException,ClassNotFoundException {
        /**
         *  资源
         */
        TableListDto listDto =  DBUtils.getTable(tableName);
        /**
         * 文件生成路径
         */
        String path = filePath+ ProjectPath.MG_WORLD+FormatUtils.toLowercase(FormatUtils.lineToHump(listDto.getTableName()))+"/ddl";
        List<MethodSpec> methodSpecList = new ArrayList<>();
        List<FieldSpec> fieldSpecs = new ArrayList<>();
        String packageName = "modules."+FormatUtils.toLowercase(FormatUtils.lineToHump(listDto.getTableName()))+".ddl";
        String className = null;
        if(!pgName.equals("/")){
            path = filePath+ProjectPath.MG_WORLD+pgName+"/ddl";
            packageName = "modules."+pgName+".ddl";
        }
        /**
         * 注释
         */
        SimpleDateFormat day  =new SimpleDateFormat("yyyy-MM-dd");
        String time = day.format(new Date());
        String doc = "Create Model By Table: << "+listDto.getTableName()+" >> On "+time+"\n";

        if(listDto!=null){
            if(listDto.getTableName()!=null){
                className = FormatUtils.captureName(FormatUtils.lineToHump(listDto.getTableName()))+"DDL" ;
            }
            if(!listDto.getList().isEmpty()){
                int primaryKeys = 0;
                for (TableDto dto : listDto.getList()){
                    Object dateType = getType(dto.getType());
                    String memberName = FormatUtils.lineToHump(dto.getColumnName());
                    String columnType = getColumnType(dto.getType());
                    List<AnnotationSpec> annotationSpecList = new ArrayList<>();
                     /**
                     * 注解
                     */
                    AnnotationSpec annotationSpec = AnnotationSpec.builder(Column.class)
                            .addMember("name", "$S", dto.getColumnName())
                            .addMember("type", "DbType."+columnType)
                            .build();
                    annotationSpecList.add(annotationSpec);
                    /**
                     * 构建主键
                     */
                    if (dto.getPrimaryKeys() && listDto.getDoublePK()){
                        AnnotationSpec annotationKey = null;
                        if(primaryKeys == 0){
                            annotationKey = AnnotationSpec.builder(FirstId.class)
                                    .build();
                            primaryKeys =1;
                        }else {
                             annotationKey = AnnotationSpec.builder(SecondId.class)
                                    .build();
                        }
                        annotationSpecList.add(annotationKey);
                    }

                    if((!listDto.getDoublePK()) && dto.getPrimaryKeys()){
                        AnnotationSpec spec = AnnotationSpec.builder(Id.class).build();
                        annotationSpecList.add(spec);
                    }

                    /**
                     *    属性
                     */
                    FieldSpec android = FieldSpec.builder(dateType.getClass(), memberName)
                            .addModifiers(Modifier.PRIVATE)
                            .addAnnotations(annotationSpecList)//添加注解
                            .build();
                    fieldSpecs.add(android);
                    /**
                     * get/set 方法
                     */
                    String methodName = FormatUtils.captureName(memberName);
                    MethodSpec GET = MethodSpec.methodBuilder("get"+methodName) //设置方法名
                            .addModifiers(Modifier.PUBLIC)//Modifier 修饰的关键字
                            .returns(TypeName.get(dateType.getClass()))//设置返回参数类型
                            .addCode(CodeBlock.builder().add("return "+memberName+";\n").build())//设置方法body
                            .build();
                    MethodSpec SET = MethodSpec.methodBuilder("set"+methodName) //设置方法名
                            .addModifiers(Modifier.PUBLIC)//Modifier 修饰的关键字
                            .addParameter(dateType.getClass(),memberName)//设置方法参数
                            .addCode(CodeBlock.builder().add("this."+memberName+" = "+memberName+";\n").build())
                            .build();
                    methodSpecList.add(GET);
                    methodSpecList.add(SET);
                }

            }
        }

        /**
         * 类注解
         */
        AnnotationSpec annotationSpec = AnnotationSpec.builder(Table.class)
                .addMember("name", "$S", listDto.getTableName())
                .build();

        TypeSpec typeSpec = TypeSpec.classBuilder(className)//类名
                .addModifiers(Modifier.PUBLIC)
                .superclass(BaseDDL.class)
                .addMethods(methodSpecList)
                .addJavadoc(doc)
                .addAnnotation(annotationSpec)
                .addFields(fieldSpecs)//在类中添加成员属性
                .build();

        JavaFile javaFile = JavaFile.builder(packageName+";\nimport jws.dal.common.DbType", typeSpec)
                .build();
      //  javaFile.writeTo(System.out);

        FileUtils.writeJavaFile(path,className+".java",javaFile.toString());
    }

    /**
     * 获取数据类型对象
     * @param type
     * @return
     */
    public static Object getType(String  type){
        Object dateType = type;
        if (type.equals("INT")||type.equals("TINYINT")|| type.equals("SMALLINT") || type.equals("BIGINT")){
            dateType = new Integer(0);
        }
        if (type.equals("CHAR") || type.equals("VARCHAR") || type.equals("TEXT") || type.equals("BLOB")){
            dateType = new String();
        }
        if (type.equals("FLOAT")){
            dateType = new Float(0);
        }
        if (type.equals("DOUBLE")){
            dateType = new Double(0);
        }
        if (type.equals("DATETIME") ||type.equals("TIMESTAMP")){
            dateType = new Long(0);
        }
        if (type.equals("DECIMAL")){
            dateType = new BigDecimal(0);
        }
        return dateType;
    }

    /**
     * MYSQL与JAVA数据类型转化
     * @param type
     * @return
     */
    public static String getColumnType(String  type){

        if (type.equals("TINYINT")){
            return "TinyInt";
        }
        if (type.equals("SMALLINT")){
            return "SmallInt";
        }
        if (type.equals("BIGINT")){
            return "BigInt";
        }
        if (type.equals("DATETIME")){
            return  "DateTime";
        }
        if (type.equals("TIMESTAMP")){
            return  "DateTime";
        }

        String str = FormatUtils.toLowercase(type);
        return FormatUtils.captureName(str);
    }



}
